﻿/**
 *@description: 进场动画，从无到有
 *@file: approach_test.cpp
 *@author: snow-tyan
 *@email: zziywang@163.com
 *@date: 23 February 2023
 *@copyright: 2018-2022 AiRiA. All rights reserved.
 */

#include "mygl/util.h"
#include "mygl/shader.h"
#include "mygl/texture2d.h"
#include "mygl/resource_manager.h"
#include "mygl/transition_renderer.hpp"
#include <GLFW/glfw3.h>
#include <iostream>

#ifndef PROJECT_ROOT
#define PROJECT_ROOT "F:/VisualStudioProjects/my-open-gl"
#endif

using namespace mygl;

const std::string kShaderRoot =
    PROJECT_ROOT + std::string("/07-InPractice/04-TransitionTest/shader/");
const std::string kTransitionRoot =
    PROJECT_ROOT + std::string("/07-InPractice/04-TransitionTest/transition_impl/");
const std::string kTextureRoot = PROJECT_ROOT + std::string("/resources/textures/");
const unsigned int kWindowWidth = 800;
const unsigned int kWindowHeight = 600;
const char* kWindowName = "ApproachTest";

void ProcessInput(GLFWwindow* window);
void FramebufferSizeCallback(GLFWwindow* window, int width, int height);
GLuint InitRenderData();

int main() {
  glfwInit();
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

  GLFWwindow* window =
      glfwCreateWindow(kWindowWidth, kWindowHeight, kWindowName, nullptr, nullptr);
  glfwMakeContextCurrent(window);
  glfwSetFramebufferSizeCallback(window, FramebufferSizeCallback);

  // glad: load all OpenGL function pointers
  if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
    std::cout << "Failed to initialize GLAD" << std::endl;
    return -1;
  }
#ifdef _DEBUG
  printf("GL_VENDOR: %s\n", glGetString(GL_VENDOR));    // 打印gl供应商
  printf("GL_VERSION: %s\n", glGetString(GL_VERSION));  // 打印gl版本
  int max_attributes;
  glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_attributes);  // 硬件支持的最大顶点属性数量
  printf("Max number of vertex attribute supported: %d\n", max_attributes);
#endif
  glEnable(GL_BLEND);  // 启用混合
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  //  Load Shaders
  ResourceManager::LoadShader("common", kShaderRoot + "shader.vert",
                              kShaderRoot + "shader.frag");
  ResourceManager::LoadShader("approach_anime", kShaderRoot + "shader.vert",
                              kShaderRoot + "approach_impl.frag",
                              kTransitionRoot + "bounce.glsl");
  ResourceManager::LoadShader("exit_anime", kShaderRoot + "shader.vert",
                              kShaderRoot + "exit_impl.frag",
                              kTransitionRoot + "wipe_right.glsl");
  // Load Textures
  ResourceManager::LoadTexture("skiing", kTextureRoot + "skiing.jpg");
  ResourceManager::LoadTexture("background", kTextureRoot + "background.jpg");
  // ResourceManager::LoadTexture("meeting", kTextureRoot + "meeting.jpg");
  // ResourceManager::LoadTexture("wb", kTextureRoot + "whiteboard.jpg");
  // Configure Shader
  ResourceManager::GetShader("approach_anime")->UseProgram();
  ResourceManager::GetShader("approach_anime")->SetUniformInt("image", 0);
  glm::mat4 projection =
      glm::ortho(0.0f, float(kWindowWidth), float(kWindowHeight), 0.0f, -1.0f, 1.0f);
  ResourceManager::GetShader("approach_anime")
      ->SetUniformMat4Float("projection", projection);
  ResourceManager::GetShader("exit_anime")->UseProgram();
  ResourceManager::GetShader("exit_anime")->SetUniformInt("image", 0);
  ResourceManager::GetShader("exit_anime")->SetUniformMat4Float("projection", projection);

  // Init Render
  auto approach_renderer = std::make_shared<TransitionRenderer>(
      ResourceManager::GetShader("approach_anime"), kWindowWidth, kWindowHeight);
  auto exit_renderer = std::make_shared<TransitionRenderer>(
      ResourceManager::GetShader("exit_anime"), kWindowWidth, kWindowHeight);
  auto common_renderer = std::make_shared<TransitionRenderer>(
      ResourceManager::GetShader("common"), kWindowWidth, kWindowHeight);

  float last_frame = 0.0f;
  float delta_time = 0.0f;
  // render loop
  while (!glfwWindowShouldClose(window)) {
    // input
    ProcessInput(window);
    float current_time = static_cast<float>(glfwGetTime());
    delta_time = current_time - last_frame;
    last_frame = current_time;
    float progress = current_time / 5;

    // render
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // 基于时间
    printf("progress=%lf\n", progress);
    int pro_integer = static_cast<int>(progress);
    float pro_decimal = progress - pro_integer;  // 小数部分从0到1增长
    // center position
    glm::vec2 position = glm::vec2(kWindowWidth / 4, kWindowHeight / 4);
    glm::vec2 size = glm::vec2(kWindowWidth / 2, kWindowHeight / 2);

    float position_scale = 0;  //

    common_renderer->Render(ResourceManager::GetTexture("background"), glm::vec2(0, 0),
                            glm::vec2(kWindowWidth, kWindowHeight));
    if (pro_integer < 1) {
      position *= (1 + pro_decimal);
      approach_renderer->RenderTransition(ResourceManager::GetTexture("skiing"),
                                          pro_decimal, position, size);
    } else if (pro_integer < 2) {
      exit_renderer->RenderTransition(ResourceManager::GetTexture("skiing"), pro_decimal,
                                      position, size);
    } else {
      break;
    }

    glfwSwapBuffers(window);
    glfwPollEvents();
  }
  common_renderer->Clear();
  approach_renderer->Clear();
  exit_renderer->Clear();
  mygl::ResourceManager::Clear();
  glfwTerminate();
  return 0;
}

void ProcessInput(GLFWwindow* window) {
  if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
    glfwSetWindowShouldClose(window, true);
  }
}

void FramebufferSizeCallback(GLFWwindow* window, int width, int height) {
  glViewport(0, 0, width, height);
}